/*
* wpxmlrpc.cpp - This file is the part of the wp-notifier.(code name "luan luan")
* Copyright (C) 2010 Dean Lee <deanlee3@gmail.com>, http://www.deanlee.cn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
* Acknowledgements:
*   <> Many thanks to all of you, who have encouraged me to update my articles
*     and code, and who sent in bug reports and fixes.
* 
*/
#include "wpxmlrpc.h"
#include "mainwin.h"
#include "configdlg.h"
#include "common.h"
#include "blog.h"

QList<wpCommand*> wpCommand::s_runningCommands;
void wpCommand::shutDownAllCommands()
{
	foreach(wpCommand* command, s_runningCommands) {
		command->m_client->abort();
	}
}

wpCommand::wpCommand(wpCommand::Type type, const Blog& blog, QObject* parent, bool autoDelete) : QObject(parent)
{
	init(type, blog.xmlrpcUrl(), blog.id(), blog.userName(), blog.password(), autoDelete);
}

wpCommand::wpCommand(wpCommand::Type type, const QString& webaddress, 
					 int blogid, const QString& username, const QString& password, 
					 QObject* parent, bool autoDelete) : QObject(parent)
{
	init(type, webaddress, blogid, username, password, autoDelete);
}

void wpCommand::init(wpCommand::Type type, const QString& webaddress, int blogid, const QString& username, 
					 const QString& password, bool autoDelete)
{
	s_runningCommands << this;
	m_blogid = blogid;
	m_type = type;
	m_autoDelete = autoDelete;
	m_url = webaddress;
	m_username = username;
	m_password = password;
	m_client = new XmlRpcClient(m_url.host(), m_url.path(), m_url.port(80));
	connect( m_client, SIGNAL(dataReady(const QVariant&, const QString&) ), this, SLOT( _onDataReady(const QVariant&, const QString&) ) );
	connect( m_client, SIGNAL(error(const QString &)), this, SLOT(_onError(const QString&)));
}

void wpCommand::executeCommand(const QString &method, const QVariantList &params)
{
	m_client->execute(method, params);
	static QString message[] = {tr("Get comments status..."), tr("Fetching comments..."), tr("Get comment"), tr("Get blog info..."),
		tr("reply comment..."), tr("Deleting comment..."), tr("Editing comment...")};
	MainWindow::instance()->busy(message[m_type]);
}

wpCommand::~wpCommand()
{
	delete m_client;
	int index = s_runningCommands.indexOf(this);
	Q_ASSERT(index != -1);
	s_runningCommands.removeAt(index);

}

void wpCommand::_onDataReady( const QVariant &response, const QString& err )
{
	MainWindow::instance()->noBusy();
	m_error = QString::fromUtf8(err.toAscii());
	bool bResult = false;
	if (m_error.isEmpty()) {
		bResult = onDataReady(response);
		if (!bResult)
			m_error = tr("Invalid response data");
	}
	emit finished(bResult);
	if (m_autoDelete)
		deleteLater();
}

void wpCommand::onError(const QString& error)
{
	MainWindow::instance()->noBusy();
	m_error = error;
	emit finished(false);
}

void wpCommand::_onError(const QString& err)
{
#ifdef _DEBUG
	qDebug() << err;
#endif
	MainWindow::instance()->noBusy();

	onError(err);
	if (m_autoDelete)
		deleteLater();
}


wpGetCommentCount::wpGetCommentCount(const Blog& blog, QObject* parent) :
	wpCommand(wpCommand::GetCommentsCount, blog, parent)
{
}

wpGetCommentCount::~wpGetCommentCount()
{
}

void wpGetCommentCount::execute(int postid)
{
	QVariantList params;
	params << m_blogid << m_username << m_password << postid;
	executeCommand("wp.getCommentCount", params);
}


bool wpGetCommentCount::onDataReady( const QVariant &response )
{
	if (response.type() == QVariant::Map) {
		QMap<QString, QVariant> params = response.toMap();
		approved = params.value("approved").toInt();
		awaiting_moderation = params.value("awaiting_moderation").toInt();
		spam = params.value("spam").toInt();
		total_comments = params.value("total_comments").toInt();
		return true;
	}
	return false;
}


wpGetComments::wpGetComments(const Blog& blog, wpGetComments::OperationType optType, QObject* parent) :
	wpCommand(wpCommand::GetComments, blog, parent),
	m_nOffset(0),
	m_operationType(optType)
{

}

wpGetComments::~wpGetComments()
{
}

void wpGetComments::execute(int postid, const QString status, int offset, int number)
{
	QVariantList params;
	QMap<QString, QVariant> map;
	map.insert("postid", postid);
	map.insert("status", status);
	map.insert("offset", offset);
	map.insert("number", number);
	params << m_blogid << m_username << m_password << map;
	m_status = status;
	m_nOffset = offset;
	executeCommand("wp.getComments", params);
}

bool wpGetComments::onDataReady( const QVariant &response)
{
	if (response.type() == QVariant::List) {
		QList<QVariant> comments = response.toList();
		foreach(QVariant v, comments) {
			QMap<QString, QVariant> p = v.toMap();
			Comment c;// = new Comment();	
			c.fromMap(p);
			/*c->m_comment_id = p.value("comment_id").toInt();
			c->m_user_id = p.value("user_id").toInt();

			c->m_comment_parent = p.value("parent").toInt();
			c->m_status = Comment::stringToStatus(p.value("status").toString());
			c->m_link = p.value("link").toString();
			c->m_post_id = p.value("post_id").toInt();
			c->m_author_url = p.value("author_url").toString();
			c->m_author_email = p.value("author_email").toString();
			c->m_author_ip = p.value("author_ip").toString();
			c->m_dateCreated = p.value("date_created_gmt").toDateTime();
			c->m_content = QString::fromUtf8(p.value("content").toString().toAscii());
			c->m_author = QString::fromUtf8(p.value("author").toString().toAscii());
			c->m_post_title = QString::fromUtf8(p.value("post_title").toString().toAscii());
			c->m_dateDiff = dateDiffString(c->m_dateCreated);*/
			m_comments << c;
		}
		return true;
	}
	return false;
}


wpGetAllComments::wpGetAllComments(const Blog* blog, QObject* parent) :
	m_blog(blog),
	m_count(0)
{
	m_approve = m_spam = m_hold = 0;
}

wpGetAllComments::~wpGetAllComments()
{
}

void wpGetAllComments::xmlrpcFinished(bool success)
{
	wpCommand* command = (wpCommand*)sender();
	if (!success) {
		m_error = command->error();
		emit finished(false);
		deleteLater();

	}
	else if (command->type() == wpCommand::GetCommentsCount) {
		wpGetCommentCount *cmd = (wpGetCommentCount*)command;
		m_approve = cmd->approved;
		m_hold = cmd->awaiting_moderation;
		m_spam = cmd->spam;
		for (int i = 0; i <= CommentData::spam; ++i) {
			wpGetComments *cmd = new wpGetComments(*m_blog, wpGetComments::Refresh, this);
			connect(cmd, SIGNAL(finished(bool)), SLOT(xmlrpcFinished(bool)));
			cmd->execute(0,  Comment::statusToString((CommentData::CommentStatus)i), 0, s_opt.m_pageSize);
		}
	}
	else if (command->type() == wpCommand::GetComments) {
		wpGetComments* cmd = (wpGetComments*)command;
		m_comments << cmd->m_comments;
		if (++m_count == CommentData::spam) {
			emit finished(true);
			deleteLater();
		}
	}
}

void wpGetAllComments::execute(int postid, int number)
{
	wpGetCommentCount* cmd = new wpGetCommentCount(*m_blog, this);
	connect(cmd, SIGNAL(finished(bool)), SLOT(xmlrpcFinished(bool)));
	cmd->execute(0);
	/*for (int i = 0; i <= CommentData::spam; ++i) {
	
		wpGetComments *cmd = new wpGetComments(*m_blog, wpGetComments::Refresh, this);
		connect(cmd, SIGNAL(finished(bool)), SLOT(xmlrpcFinished(bool)));
		cmd->execute(postid,  Comment::statusToString((CommentStatus)i), 0, number);
	}*/
}


wpGetUsersBlogs::wpGetUsersBlogs(const QString& webaddress, const QString& username, const QString& password, QObject* parent) :
	wpCommand(wpCommand::BlogInfo, webaddress, 0, username, password, parent)
{

}

wpGetUsersBlogs::~wpGetUsersBlogs()
{
	m_blogs.clear();
}

void wpGetUsersBlogs::execute()
{
	QVariantList params;
	params << m_username << m_password;
	executeCommand("wp.getUsersBlogs", params);	
}

bool wpGetUsersBlogs::onDataReady( const QVariant &response)
{
	bool success = false;
	if (response.type() == QVariant::List) {
		// Get the first blog
		foreach(QVariant val, response.toList())
		{
			QMap<QString, QVariant> params = val.toMap();
			Blog blog;
			//blog.setUrl(m_url.host());
			blog.setUserName(m_username);
			blog.setPassword(m_password);
			blog.setIsAdmin(params.value("isAdmin").toBool());
			blog.setUrl(params.value("url").toString());
			blog.setId(params.value("blogid").toInt());
			blog.setName(QString::fromUtf8(params.value("blogName").toString().toAscii()));
			blog.setXmlrpcUrl(params.value("xmlrpc").toString());
			m_blogs << blog;
		}
		success = true;
	}
	return success;
}


wpDeleteComment::wpDeleteComment(const Blog& blog, QObject* parent) : 
	wpCommand(wpCommand::DeleteComment, blog, parent)
{
}

wpDeleteComment::~wpDeleteComment()
{
}

void wpDeleteComment::execute(int comment_id)
{
	QVariantList params;
	params << m_blogid << m_username << m_password << comment_id;
	executeCommand("wp.deleteComment", params);
}

bool wpDeleteComment::onDataReady( const QVariant &response)
{
	return true;
}

wpNewComment::wpNewComment(const Blog& blog, QObject* parent) : 
	wpCommand(wpCommand::NewComment, blog, parent)
{
	m_commentid = 0;
}

wpNewComment::~wpNewComment()
{
}

void wpNewComment::execute(int postid, int comment_parent, const QString& content)
{
	QVariantList params;
	QMap<QString, QVariant> map;
	map.insert("comment_parent", comment_parent);
	map.insert("content", escapedString(content).toUtf8());

	params << m_blogid << m_username << m_password << postid << map;
	executeCommand("wp.newComment", params);
}

bool wpNewComment::onDataReady( const QVariant &response)
{
	if (response.canConvert<int>()) {
		m_commentid = response.toInt();
		return true;
	}
	return false;
}

wpEditComment::wpEditComment(const Blog& blog, QObject* parent) : 
	wpCommand(wpCommand::EditComment, blog, parent)
{
}

wpEditComment::~wpEditComment()
{
}

void wpEditComment::execute(int comment_id, const QString& status, const QString& content)
{
	QVariantList params;
	QMap<QString, QVariant> map;
	map.insert("status", status);
	if (!content.isEmpty()) {
		map.insert("content", escapedString(content).toUtf8());
	}
	params << m_blogid << m_username << m_password << comment_id << map;
	executeCommand("wp.editComment", params);
}

bool wpEditComment::onDataReady( const QVariant &response)
{
	return true;
}


wpGetComment::wpGetComment(const Blog& blog, QObject* parent) : 
	wpCommand(GetComment, blog, parent)
{
//	m_comment = NULL;
}

wpGetComment::~wpGetComment()
{
}

void wpGetComment::execute(int commentid)
{
	QVariantList params;
	params << m_blogid << m_username << m_password << commentid;
	executeCommand("wp.getComment", params);
}

bool wpGetComment::onDataReady( const QVariant &response)
{
	if (response.type() == QVariant::Map) {
		m_comment.fromMap(response);// = Comment::mapToComment(response);
		return true;
	}
	return false;
}



